package com.example.doufacedemo;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.hardware.Camera;
import android.os.Environment;
import android.provider.SyncStateContract;
import android.util.Log;
import android.widget.Toast;

import com.hjimi.api.iminect.ImiCameraFrame;
import com.hjimi.api.iminect.ImiDevice;

import org.bytedeco.javacpp.BytePointer;
import org.bytedeco.javacpp.FloatPointer;
import org.bytedeco.javacpp.IntPointer;
import org.bytedeco.javacpp.Pointer;
import org.bytedeco.xhfacelite.global.xhfacelite;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

import static com.example.doufacedemo.MyApp.sess;
import static kotlin.text.Typography.times;

public class DouFacePayUtils {
    private static int N = 2;


    //插入
    static Integer faceIntert(xhfacelite.XHF_SESS sess) {
        //3.1 将人脸头像插入本地算法库
        BitmapFactory.Options opt = new BitmapFactory.Options();
        opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
        Log.i("main", "path = " + Environment.getExternalStorageDirectory().toString() + "/test.jpg");
        //测试图片路径 请自行修改
        Bitmap img = BitmapFactory.decodeFile
                (Environment.getExternalStorageDirectory().toString() + "/test.jpg", opt); //test.jpg 图片路径
        byte[] data = bitmap2Byte(img, 3); // ARGB_8888转BGR
        IntPointer index = new IntPointer(1);
        xhfacelite.FaceRectPtr max_face = new xhfacelite.FaceRectPtr();
        // 插入后需调用FESave保存，否则只在内存生效，可多次插入后周期性保存，减少磁盘访问
        // index 表示当前人脸照片在算法库的唯一索引
        int xhf_code = xhfacelite.FEInsert(sess, new BytePointer(data), img.getWidth(), img.getHeight(), index, max_face);
        Toast.makeText(MyApp.mContext,"插入后的code = "+xhf_code,Toast.LENGTH_SHORT);
        Log.i("main", "步骤3.1:插入算法到内存 = " + xhf_code);
        return xhf_code;

    }

    static byte[] bitmap2Byte(Bitmap img, int flag) {
        int width = img.getWidth();
        int height = img.getHeight();
        int[] argb = new int[width * height];
        img.getPixels(argb, 0, width, 0, 0, width, height);
        byte[] data = new byte[width * height * flag];
        for (int i = 0; i < argb.length; ++i) {
            for (int c = 0; c < flag; ++c) {
                data[i * flag + c] = (byte) ((argb[i] >> (c * 8)) & 0xFF);
            }
        }
        return data;
    }


    public static void onCreateFaceInterface(Context context) {
        xhfacelite.XHF_SESS sess = new xhfacelite.XHF_SESS(new Pointer());
        MyApp.sess = sess;
        int code = xhfacelite.FECreate(sess);
        Log.i("sss", "创建会话窗口 =" + code);
        faceIntert(sess);
        faceSave(sess, context);
    }

     static void faceSave(xhfacelite.XHF_SESS sess, Context context) {
        //3.2 需要保存人脸数据草本地
        int code = xhfacelite.FESave(sess, new File(context.getExternalFilesDir("FaceDB") + File.separator + "face_db").toString());

         Log.i("main", "步骤3.2:保存人脸数据草本地 = " + code);
    }


    /**
     * 人脸识别图片
     */
    public static int dealBitmap(Bitmap bmp, Matrix matrix,xhfacelite.XHF_SESS sess) {

        try {
//            //region 帧图数据处理
//            Camera.Size size = camera.getParameters().getPreviewSize();//获得预览图像设置的尺寸
//            BitmapFactory.Options opt = new BitmapFactory.Options();
//            opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
            //图片流需要转换格式
//            YuvImage image = new YuvImage(data, ImageFormat.NV21, width, height, null);
//            ByteArrayOutputStream stream = new ByteArrayOutputStream();
//            image.compressToJpeg(new Rect(0, 0, width, height), 100, stream);
//            Bitmap bmp = BitmapFactory.decodeByteArray(stream.toByteArray(), 0, stream.toByteArray().length);
//            //旋转、压缩图片
//            ByteArrayOutputStream stream2 = new ByteArrayOutputStream();

            Bitmap img = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
            byte[] dataImg = bitmap2Byte(img, 3);
            IntPointer index_list =   new IntPointer(N);
            FloatPointer score_list =   new FloatPointer(N);
            IntPointer list_length =    new IntPointer(1);
            int code = xhfacelite.FEQueryTopN(sess,  new BytePointer(dataImg), img.getWidth(), img.getHeight(), index_list, score_list, list_length);
            Log.i("main", "score_list = " + score_list.get());
            Log.i("main", "识别后的结果 = " + code);
            if (code ==0){
                return code;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -1;
    }

    static xhfacelite.XHF_SESS FECreate() {
        xhfacelite.XHF_SESS sess = new xhfacelite.XHF_SESS(new Pointer());
        MyApp.sess = sess;
        int code = xhfacelite.FECreate(sess);
        Log.i("main", "步骤2:创建窗口 = " + code);
        return sess;
    }

    static void FEload() {
        int ELoadcode = xhfacelite.FELoad(
                sess,
                MyApp.mContext.getExternalFilesDir("FaceDB").toString() + File.separator + "face_db"
        );
        Log.i("main", "步骤3：加载算法  = " + ELoadcode);
    }

    static void FEdestory(xhfacelite.XHF_SESS xhf_sess) {
        int FEDestroyCode = xhfacelite.FEDestroy(xhf_sess);
        Log.i("main", "销毁 = " + FEDestroyCode);
        xhfacelite.XHFFinal();
    }

    /**
     * ----------------------------------------rgb24转bitmap---------------------------------------------------------------
     */
    static Bitmap rgb2Bitmap(byte[] data, int width, int height) {
        int[] colors = convertByteToColor(data);    //取RGB值转换为int数组
        if (colors == null) {
            return null;
        }

        Bitmap bmp = Bitmap.createBitmap(colors, 0, width, width, height,
                Bitmap.Config.ARGB_8888);
        return bmp;
    }

    // 将一个byte数转成int
    // 实现这个函数的目的是为了将byte数当成无符号的变量去转化成int
    public static int convertByteToInt(byte data) {

        int heightBit = (int) ((data >> 4) & 0x0F);
        int lowBit = (int) (0x0F & data);
        return heightBit * 16 + lowBit;
    }

    // 将纯RGB数据数组转化成int像素数组
    public static int[] convertByteToColor(byte[] data) {
        int size = data.length;
        if (size == 0) {
            return null;
        }

        int arg = 0;
        if (size % 3 != 0) {
            arg = 1;
        }

        // 一般RGB字节数组的长度应该是3的倍数，
        // 不排除有特殊情况，多余的RGB数据用黑色0XFF000000填充
        int[] color = new int[size / 3 + arg];
        int red, green, blue;
        int colorLen = color.length;
        if (arg == 0) {
            for (int i = 0; i < colorLen; ++i) {
                red = convertByteToInt(data[i * 3]);
                green = convertByteToInt(data[i * 3 + 1]);
                blue = convertByteToInt(data[i * 3 + 2]);

                // 获取RGB分量值通过按位或生成int的像素值
                color[i] = (red << 16) | (green << 8) | blue | 0xFF000000;
            }
        } else {
            for (int i = 0; i < colorLen - 1; ++i) {
                red = convertByteToInt(data[i * 3]);
                green = convertByteToInt(data[i * 3 + 1]);
                blue = convertByteToInt(data[i * 3 + 2]);
                color[i] = (red << 16) | (green << 8) | blue | 0xFF000000;
            }

            color[colorLen - 1] = 0xFF000000;
        }

        return color;
    }
}
